package cn.wolfcode.audit.service.impl;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

import cn.wolfcode.audit.domain.AudBpmnInfo;
import cn.wolfcode.audit.dto.AudCarPackageDTO;
import cn.wolfcode.audit.dto.AudedCarPackageDTO;
import cn.wolfcode.audit.vo.TaskHistoryVO;
import cn.wolfcode.business.domain.BusServiceItem;
import cn.wolfcode.business.mapper.BusServiceItemMapper;
import cn.wolfcode.common.constant.AuditConstants;
import cn.wolfcode.common.constant.BusinessConstants;
import cn.wolfcode.common.utils.DateUtils;
import cn.wolfcode.common.utils.SecurityUtils;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.persistence.entity.CommentEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.bcel.generic.ARRAYLENGTH;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import cn.wolfcode.audit.mapper.AudCarPackageMapper;
import cn.wolfcode.audit.domain.AudCarPackage;
import cn.wolfcode.audit.service.IAudCarPackageService;

/**
 * 套餐审核Service业务层处理
 * 
 * @author zhangyf
 * @date 2023-04-17
 */
@Service
public class AudCarPackageServiceImpl implements IAudCarPackageService 
{
    @Autowired
    private AudCarPackageMapper audCarPackageMapper;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private BusServiceItemMapper busServiceItemMapper;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private HistoryService historyService;

    /**
     * 查询套餐审核
     * 
     * @param id 套餐审核主键
     * @return 套餐审核
     */
    @Override
    public AudCarPackage selectAudCarPackageById(Long id)
    {
        return audCarPackageMapper.selectAudCarPackageById(id);
    }

    /**
     * 查询套餐审核列表
     * 
     * @param audCarPackage 套餐审核
     * @return 套餐审核
     */
    @Override
    public List<AudCarPackage> selectAudCarPackageList(AudCarPackage audCarPackage)
    {
        return audCarPackageMapper.selectAudCarPackageList(audCarPackage);
    }

    /**
     * 新增套餐审核
     * 
     * @param audCarPackage 套餐审核
     * @return 结果
     */
    @Override
    public int insertAudCarPackage(AudCarPackage audCarPackage)
    {
        audCarPackage.setCreateTime(DateUtils.getNowDate());
        return audCarPackageMapper.insertAudCarPackage(audCarPackage);
    }

    /**
     * 修改套餐审核
     * 
     * @param audCarPackage 套餐审核
     * @return 结果
     */
    @Override
    public int updateAudCarPackage(AudCarPackage audCarPackage)
    {
        return audCarPackageMapper.updateAudCarPackage(audCarPackage);
    }

    /**
     * 批量删除套餐审核
     * 
     * @param ids 需要删除的套餐审核主键
     * @return 结果
     */
    @Override
    public int deleteAudCarPackageByIds(Long[] ids)
    {
        return audCarPackageMapper.deleteAudCarPackageByIds(ids);
    }

    /**
     * 删除套餐审核信息
     * 
     * @param id 套餐审核主键
     * @return 结果
     */
    @Override
    public int deleteAudCarPackageById(Long id)
    {
        return audCarPackageMapper.deleteAudCarPackageById(id);
    }

    @Override
    public int startAuditServiceItem(AudCarPackageDTO audCarPackageDTO) {
        BusServiceItem busServiceItem = busServiceItemMapper.selectBusServiceItemById(audCarPackageDTO.getId());
        String businessKey = audCarPackageDTO.getId().toString();  // 存服务项id
        Map<String, Object> variables = new HashMap<>();    // 设置流程变量值
        variables.put("disCountPrice",busServiceItem.getDiscountPrice().longValue());
        variables.put("shopOwnerId",audCarPackageDTO.getShopOwnerId());
        // 判断
        if(audCarPackageDTO.getFinanceId() != null){
            variables.put("financeId",audCarPackageDTO.getFinanceId());
        }

        // todo 写死key了
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("bus_car_package",
                businessKey, variables);

        // 修改对应服务项的状态为审核中
        busServiceItem.setAuditStatus(BusinessConstants.AUDIT_STATUS_PENDING);
        busServiceItemMapper.updateBusServiceItem(busServiceItem);

        // 往aud_car_package 表存数据
        AudCarPackage audCarPackage = new AudCarPackage();

        audCarPackage.setInstanceId(processInstance.getId());
        audCarPackage.setServiceItemId(busServiceItem.getId());
        audCarPackage.setServiceItemName(busServiceItem.getName());
        audCarPackage.setServiceItemPrice(busServiceItem.getDiscountPrice());
        audCarPackage.setServiceItemInfo(busServiceItem.getInfo());
        audCarPackage.setStatus(AuditConstants.CAR_PACKAGE_STATUS_PENDING);


        audCarPackage.setCreatorId(SecurityUtils.getUserId().toString());
        audCarPackage.setCreateTime(DateUtils.getNowDate());
        audCarPackage.setCreateBy(SecurityUtils.getUsername());
        audCarPackage.setInfo(busServiceItem.getInfo());

        return audCarPackageMapper.insertAudCarPackage(audCarPackage);
    }

    @Override
    /*
        1.先查询自己任务，获取流程实例id
        2. 再根据流程实例id，过滤 表aud_car_package 中的数据
     */
    public List<AudCarPackage> listToDoCarPackage() {
        // 获取当前的登录的用户，即是查看待办任务的用户
        String userId = SecurityUtils.getLoginUser().getUserId().toString();
        // 查询当前用户套餐审核任务
        List<Task> tasks = taskService.createTaskQuery()
                .taskAssignee(userId)   // 指定查询哪个用户
                .processDefinitionKey("bus_car_package")    // 通过key指定流程
                .list();

        if(tasks.size() == 0){
            return Collections.emptyList();
        }

      /*  // List<Task>  Set<String>  使用lambda表达式
        for (Task task : tasks) {
            // 获取任务对应流程实例 id
            String processInstanceId = task.getProcessInstanceId();
        }*/
        // 获取流程实例 id
        Set<String> processInstanceIds = tasks.stream()
                .map(task -> task.getProcessInstanceId())
                .collect(Collectors.toSet());

        if(processInstanceIds.size() == 0){
            return Collections.emptyList();
        }

        return audCarPackageMapper.selectAudCarPackageByProcessInstanceIds(processInstanceIds);
    }

    @Override
    public void auditServiceItem(AudedCarPackageDTO audedCarPackageDTO) {
        String processInstanceId = audedCarPackageDTO.getProcessInstanceId();
        String info = "[" + SecurityUtils.getUsername() + ":]" + audedCarPackageDTO.getInfo();
        Task task = taskService.createTaskQuery()
                .taskAssignee(SecurityUtils.getUserId().toString())
                .processInstanceId(processInstanceId)
                .singleResult();
        // 先添加审核备注再去完成审核（complete）。因为完成审核后，运行的任务表数据就会清空，表都清空了，你怎样去添加审核备注。
        // 添加审核备注
        taskService.addComment(task.getId(),processInstanceId,info);
        Map<String,Object> variables = new HashMap<>();
        boolean status = audedCarPackageDTO.isStatus();
        variables.put("shopOwner", status);
        // 审核任务
        taskService.complete(task.getId(),variables);

        if(status){ //审核通过
            if(taskService.createTaskQuery()
            .processInstanceId(processInstanceId)
            .list().size() == 0){   // 后面没任务
                // 把套餐审核信息数据和服务项数据状态改成审核通过
                AudCarPackage audCarPackage = audCarPackageMapper.selectAudCarPackageByProcessInstanceId(processInstanceId);
                audCarPackage.setStatus(AuditConstants.CAR_PACKAGE_STATUS_SUCCESS);
                audCarPackageMapper.updateAudCarPackage(audCarPackage);
                BusServiceItem busServiceItem = busServiceItemMapper.selectBusServiceItemById(audCarPackage.getServiceItemId());
                busServiceItem.setAuditStatus(BusinessConstants.AUDIT_STATUS_SUCCESS);
                busServiceItemMapper.updateBusServiceItem(busServiceItem);
            }

        }else{  // 审核拒绝
            // 把套餐审核信息数据和服务项数据状态改成审核拒绝
            AudCarPackage audCarPackage = audCarPackageMapper.selectAudCarPackageByProcessInstanceId(processInstanceId);
            audCarPackage.setStatus(AuditConstants.CAR_PACKAGE_STATUS_FAIL);
            audCarPackageMapper.updateAudCarPackage(audCarPackage);
            BusServiceItem busServiceItem = busServiceItemMapper.selectBusServiceItemById(audCarPackage.getServiceItemId());
            busServiceItem.setAuditStatus(BusinessConstants.AUDIT_STATUS_FAIL);
            busServiceItemMapper.updateBusServiceItem(busServiceItem);
        }
    }

    @Override
    public InputStream getInputStream(String instanceId) {

        // 根据流程实例id 查询流程数据
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(instanceId)
                .singleResult();

        String processDefinitionId = processInstance.getProcessDefinitionId();

        /*// 查询流程实例的任务（多任务）
        List<Task> tasks = taskService.createTaskQuery()
                .processInstanceId(instanceId)
                .list();
        List<String> executionIds = new ArrayList<>();
        for (Task task : tasks) {
            String executionId = task.getExecutionId();
            executionIds.add(executionId);
        }

        List<String> activeActivityIds = new ArrayList<>();
        for (String executionId : executionIds) {
            List<String> activityIds = runtimeService.getActiveActivityIds(executionId);
            activeActivityIds.addAll(activityIds);
        }*/

        // 查询执行任务（单任务）
        Task task = taskService.createTaskQuery()
                .processInstanceId(instanceId)
                .singleResult();
        if(task == null){
            DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
            return generator.generateDiagram(bpmnModel,
                    Collections.emptyList(),
                    Collections.emptyList(),
                    "宋体",
                    "宋体",
                    "宋体");
        }
        // 获取任务对应的节点
        String executionId = task.getExecutionId();
        // 获取节点在流程图上的坐标
        List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionId);

        DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        return generator.generateDiagram(bpmnModel,
                activeActivityIds,
                Collections.emptyList(),
                "宋体",
                "宋体",
                "宋体");
    }

    @Override
    public List<AudCarPackage> listDoneCarPackage() {
        String userId = SecurityUtils.getLoginUser().getUserId().toString();
        // 查询当前用户套餐历史审核任务（已经审核过和没有审核过都有）
        List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(userId)   // 指定查询哪个用户
                .finished() //查询已经审核过的任务
                .processDefinitionKey("bus_car_package")    // 通过key指定流程
                .list();

        if(tasks.size() == 0){
            return Collections.emptyList();
        }

        // 获取流程实例 id
        Set<String> processInstanceIds = tasks.stream()
                .map(task -> task.getProcessInstanceId())
                .collect(Collectors.toSet());

        if(processInstanceIds.size() == 0){
            return Collections.emptyList();
        }

        return audCarPackageMapper.selectAudCarPackageByProcessInstanceIds(processInstanceIds);

    }

    @Override
    public List<TaskHistoryVO> queryAuditHistories(String instanceId) {
        // 查询对应实例下的任务（包括已经审核过和没有审核过的）
        List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(instanceId)
                .list();
        if(tasks.size() == 0){
            return  Collections.emptyList();
        }
        // 存
        List<TaskHistoryVO> list = new ArrayList<>();
        // 遍历任务，把数据封装到我们 自定义的 TaskHistoryVO 对象
        for (HistoricTaskInstance task : tasks) {
            TaskHistoryVO taskHistoryVO = new TaskHistoryVO();
            taskHistoryVO.setTaskName(task.getName());

            Date startTime = task.getStartTime();
            Date endTime = task.getEndTime();

            taskHistoryVO.setStartTime(startTime);
            taskHistoryVO.setEndTime(endTime);  // task.getEndTime() 可能是null
            if(endTime != null){    // 任务完成是有结束时间的
                // 计算耗时，并封装进去
                taskHistoryVO.setDuration(DateUtils.getDatePoor(endTime,startTime));
            }
            // 查询任务对应审核备注。
            List<Comment> comments = taskService.getTaskComments(task.getId(), CommentEntity.TYPE_COMMENT);// 拿到我们自己设置的备注
            if(comments.size() > 0){
                // 若有任务有备注，则遍历把备注内容拼接字符串，封装
                StringBuilder info = new StringBuilder();
                for (Comment comment : comments) {
                    info.append(comment.getFullMessage());
                }
                taskHistoryVO.setInfo(info.toString());
            }
            list.add(taskHistoryVO);
        }
        return list;
    }

    @Override
    public void cancelCarPackage(String instanceId) {
        runtimeService.deleteProcessInstance(instanceId,"我愿意");
        AudCarPackage audCarPackage = audCarPackageMapper.selectAudCarPackageByProcessInstanceId(instanceId);
        audCarPackage.setStatus(AuditConstants.CAR_PACKAGE_STATUS_CANCELED);
        audCarPackageMapper.updateAudCarPackage(audCarPackage);
        BusServiceItem busServiceItem = busServiceItemMapper.selectBusServiceItemById(audCarPackage.getServiceItemId());
        busServiceItem.setAuditStatus(BusinessConstants.AUDIT_STATUS_FAIL);
        busServiceItemMapper.updateBusServiceItem(busServiceItem);
    }
}
